﻿#include "formeke.h"
#include "ui_formeke.h"
#include"Common/jsonmsg.h"
#include<qDebug>
#include<QStandardItemModel>
#include<QMessageBox>
#include<QAbstractTableModel>
#include"dialogmodifycase.h"
#include"dataCache/loadeketestcase.h"
#include"Tool/qfilehelper.h"
#include <Common/configData.h>
#include"dataCache/loadmvbportcache.h"
#include <UserControl/CustomItemModel.h>
#pragma execution_character_set("utf-8")
FormEKE::FormEKE(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FormEKE)
{
    ui->setupUi(this);
    initRightClickedMenu();
    connectAllSlots();
}

FormEKE::~FormEKE()
{
    if(_ekeThread!=nullptr)
    {
        _ekeThread->stop();

    }
    delete ui;
}

void FormEKE::on_btn_test_clicked()
{
    JsonMsg msg;
    //    qDebug()<<msg.GenerateWriteMsg();
}

void FormEKE::on_btn_TestCaseImport_clicked()
{
    auto filename =QFileHelper::FileSelect();
    if(filename.isEmpty())
        return;
    _OriginFile = filename;
    LoadEKETestCase testCase;
    qDebug()<<filename<<endl;
    testCase.loadEKECase(filename,_ekeDataCache);
    ShowEKEcase();
}

void FormEKE::on_btn_exportTestCase_clicked()
{
    auto filename =QFileHelper::FileSave(".xlsx");
    if(filename.isEmpty()||_OriginFile.isEmpty())
        return;

    LoadEKETestCase testCase;
    testCase.SaveEKECase("C:\\excel\\EKE\\EKEtemp.xlsx",filename,_ekeDataCache);
}


void FormEKE::connectAllSlots()
{
    connect(ui->btn_check,SIGNAL(clicked(bool)),this,SLOT(slotTestFunction()));
    connect(ui->btn_statusCheck,SIGNAL(clicked()),this,SLOT(slotBtnTestClicked()));
    connect(ui->btn_protocalImport,SIGNAL(clicked(bool)),this,SLOT(slotBtnImportProtocalClicked()));
    connect(ui->btn_resetAllPorts,SIGNAL(clicked(bool)),this,SLOT(slotBtnResetAllPorts()));
    
    connect(ui->btn_MVBConnect,SIGNAL(clicked(bool)),this,SLOT(slotConnectMVBSetver()));
    connect(&m_statusModel,SIGNAL(statusChanged()),this,SLOT(slotShowStatus()));

    connect(&m_clientForMVB,&tcpcClientForMVB::TransReadMVBData,this,&FormEKE::slotReceiveMvbData);
    connect(&m_clientForMVB,&tcpcClientForMVB::TcpMsg,this,&FormEKE::slotTransTcpMsg);
     m_treeModel = new CustomItemModel(ui->treeView);
    QObject::connect(m_treeModel, &CustomItemModel::dataChanged,this,&FormEKE::slotOnModelDataChange);
}

void FormEKE::appendEKEcase(const EKECase &ekecase, QStandardItemModel *model)
{

//    int rowCount =ekecase._mapEKEcase.count();
//    qDebug()<<"append COunt:"<<rowCount<<endl;
//    model->setRowCount(rowCount+ model->rowCount());

//     qDebug()<<"common COunt:"<<rowCount+ model->rowCount()<<endl;

//    // 填充数据
//    auto &ekedata = _ekeCase._mapEKEcase;
//    int nRowindex = model->rowCount();
//    foreach (auto& childeke,ekedata)
//    {
//        QStandardItem* item1 = new QStandardItem(childeke._childCaseNumber);
//        model->setItem(nRowindex, 0, item1);
//        QStandardItem* item2 = new QStandardItem(childeke._childCaseName);
//        model->setItem(nRowindex, 1, item2);

//        QString stringPreDiction =childeke._precondition.join(";");
//        QStandardItem* item3 = new QStandardItem(stringPreDiction);
//        model->setItem(nRowindex, 2, item3);

//        QStringList listOperator;
//        int nInputcount = childeke._inputs.count();
//        qDebug()<<"inputcount"<<nInputcount<<endl;
//        for (int i = 0; i < nInputcount; ++i)
//        {
//            QString strKeyValue=childeke._inputs[i].first+"="+childeke._inputs[i].second;
//            qDebug()<<strKeyValue<<endl;
//            listOperator<<strKeyValue;
//        }
//        QStandardItem* item4 = new QStandardItem(listOperator.join(";"));
//        model->setItem(nRowindex, 3, item4);

//        QStringList listResult;
//        int nOutputcount = childeke._output.count();
//        qDebug()<<"nOutputcount"<<nOutputcount<<endl;
//        for (int i = 0; i < nOutputcount; ++i)
//        {
//            QString strKeyValue=childeke._output[i].first+"="+childeke._output[i].second;
//            listResult<<strKeyValue;
//        }
//        QStandardItem* item5 = new QStandardItem(listResult.join(";"));
//        model->setItem(nRowindex, 4, item5);

//        nRowindex++;
//    }
}

void FormEKE::ShowAllEKEcase(const QMap<QString, EKECase> &allCase)
{
//    QStandardItemModel* model = new QStandardItemModel();

//    model->setColumnCount(7);
//    // 创建列标题
//    QStringList headers;
//    headers<<"测试编号"<<"描述"<<"前置条件"<<"操作步骤"<<"期望结果"<<"结果"<<"延时获取";
//    model->setHorizontalHeaderLabels(headers);

//     appendEKEcase(_sheetEkeCases.first(),model);
////    qDebug()<<"mapEke count:"<<_mapEkeCase.count()<<endl;
////    for (auto var = _mapEkeCase.constBegin(); var!=_mapEkeCase.constEnd(); ++var)
////    {
////        QString sheetName=var.key();
////        appendEKEcase(var.value(),model);
////        break;
////    }
//    //整行选中
//    ui->tableView_case->setSelectionBehavior(QAbstractItemView::SelectRows);
//    ui->tableView_case->setModel(model);
//    ui->tableView_case->resizeColumnsToContents();
}


void FormEKE::initRightClickedMenu()
{
    if(_menuRClick==nullptr)
        _menuRClick = new QMenu(this);
    // 创建菜单项
    QAction *actionEdit = new QAction("编辑", this);
    QAction *action2 = new QAction("测试", this);

    connect(actionEdit, &QAction::triggered, this, [=]()
    {
        QAbstractItemModel *model = ui->tableView_case->model();
        if (model)
        {
            // 检查模型是否有行
            if( model->rowCount() == 0)
            {
                qDebug()<<"model row count =0 exit"<<endl;
                return;
            }
        }
        else
        {
            qDebug()<<"no mdel exit"<<endl;
            return;
        }

        QItemSelectionModel *selectionModel = ui->tableView_case->selectionModel();

        // 检查是否有选中的项
        if (selectionModel->hasSelection())
        {
            // 获取选中的第一个项
            QModelIndex currentIndex  = selectionModel->selectedIndexes().first();
            if (currentIndex .isValid()) {
                // 假设我们关心第二列的数据（列索引为1）
                int columnToGet = 0;
                QModelIndex index = ui->tableView_case->model()->index(currentIndex .row(), columnToGet);
                QVariant data = ui->tableView_case->model()->data(index);

                // 根据需要转换数据类型
                QString stringData = data.toString();
                auto& sheetEkeCases= _ekeDataCache._sheetEkeCases;
                // 使用stringData
                for (auto sheetCase = sheetEkeCases.begin(); sheetCase !=sheetEkeCases.end(); ++sheetCase)
                {
                    auto& ekeCaseTemp =sheetCase.value();
                    if(ekeCaseTemp._mapEKEcase.keys().contains(stringData))
                    {
                        DialogModifyCase editCase(ekeCaseTemp._mapEKEcase[stringData]);
                        auto ret =editCase.exec();
                        if(ret ==QDialog::Accepted)
                        {
                            //执行修改操作
                            ekeCaseTemp._mapEKEcase[stringData]=editCase.GetChildCase();
                            ShowEKEcase();
                        }
                        else
                        {

                        }
                    }

                }

            }
        }

    });

    connect(action2, &QAction::triggered, this, [=](){
        qDebug("action2action2 click");
    });

    // 创建菜单并添加菜单项
    _menuRClick->addAction(actionEdit);
    _menuRClick->addAction(action2);

    // 为按钮设置右键菜单
    ui->tableView_case->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->tableView_case, &QTableView::customContextMenuRequested, [this](const QPoint &pos) {
        // 在鼠标点击位置显示右键菜单
        _menuRClick->exec(ui->tableView_case->mapToGlobal(pos));
    });
}

void FormEKE::ShowEKEcase()
{

    QStandardItemModel* model = new QStandardItemModel();

    _ekeDataCache.generateModel(model);

    //整行选中
    ui->tableView_case->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->tableView_case->setModel(model);

    QList<int> columnWidths;
//    columnWidths<<20<<60<<120<<240<<160<<100<<100;
    ui->tableView_case->setColumnWidth(3,600);
    ui->tableView_case->setColumnWidth(4,400);
//    ui->tableView_case->resizeColumnsToContents();
}

void FormEKE::on_btn_run_clicked()
{
    if(_ekeDataCache.getAllCaseCount()<=0)
    {
        QMessageBox::information(this,"提示","请先加载协议");
    }

    if(_ekeThread==nullptr)
    {
        _ekeThread = new EKETestThead();
        connect(_ekeThread,&EKETestThead::SendProcedureMsg,this,&FormEKE::SendLogMsg);
        connect(_ekeThread,SIGNAL(signal_UpdateUI(QString)),this,SLOT(slotUpdateResult(QString)));
        connect(_ekeThread,SIGNAL(signal_threadFinishMsg(int)),this,SLOT(slotThreadExit(int)));

    }

    _ekeThread->SetEKETestData(&_ekeDataCache);
    _ekeThread->start();
    m_statusModel.start(500);
}


void FormEKE::on_btn_pause_clicked()
{
    if(_ekeThread==nullptr)
        return;
    _ekeThread->pause();
}

void FormEKE::on_btn_stop_clicked()
{
    if(_ekeThread==nullptr)
        return;
    _ekeThread->stop();
    m_statusModel.stop();
    emit SendLogMsg(("停止.."));
}

void FormEKE::slotBtntestMVB()
{

}

void FormEKE::slotThreadExit(int n)
{
    m_statusModel.stop();
}

void FormEKE::slotBtnResetAllPorts()
{
    m_mvbProtoclaCache.resetAllDeviceData();
    slotShowProtoalData(m_mvbProtoclaCache);

}

void FormEKE::slotTransTcpMsg(const QString &msg)
{
     emit SendLogMsg(msg);
}

void FormEKE::slotConnectMVBSetver()
{
     qDebug()<<"connectToServer mvb"<<endl;
     if(m_clientForMVB.state()!=QAbstractSocket::ConnectedState)
     {

     }
     m_clientForMVB.connectToServer(ConfigData::strIP_mvb,ConfigData::strPort_mvb.toInt());

}

void FormEKE::slotReceiveMvbData(QByteArray &mvbProtocalCache)
{
    qDebug()<<"read mvb";
    emit SendLogMsg("read mvb");
    QDataStream readMVBstream(mvbProtocalCache);
    readMVBstream.setVersion(QDataStream::Qt_5_12);

    QString portAddress;
    QByteArray MVbdata;

    m_mvbProtoclaCache.m_portCache;
    mvbDeviceData devicedata;
    //读取所有端口缓存数据
    while (!readMVBstream.atEnd())
    {
        readMVBstream>>portAddress;
        readMVBstream>>MVbdata;
        devicedata.deserialize(MVbdata);
        m_mvbProtoclaCache.m_portCache[portAddress]=devicedata;
    }

    //显示数据
    m_mvbProtoclaCache.TransCacheToDataPars();
    slotShowProtoalData(m_mvbProtoclaCache);
}

void FormEKE::slotUpdateResult(const QString& testCaseNumber)
{
    QAbstractItemModel *model = ui->tableView_case->model();

    int nRecentID;
    // 遍历所有行和列
    for (int row = 0; row < model->rowCount(); ++row)
    {
        // 获取单元格数据，这里使用了Qt::DisplayRole来获取显示的文本
        QVariant data = model->data(model->index(row,0), Qt::DisplayRole);

        // 假设数据是字符串，将其转换为QString
        QString strData = data.toString();
        if(testCaseNumber==strData)
        {
            ekeResult result =_ekeDataCache.getResultByTestCaseNumber(testCaseNumber);
            model->setData(model->index(row, 6),result._bPass);
            nRecentID=row;
        }
    }

    //更新状态栏显示 根据处理数据来更新状态栏
    updateStatusInfo_Process(nRecentID);


}

void FormEKE::slotTestFunction()
{
    slotTestEke();
}

void FormEKE::slotTestEke()
{
    if(_ekeDataCache.getAllCaseCount()<=0)
    {
        QMessageBox::information(this,"提示","请先加载数据");
        return;
    }
    QItemSelectionModel *selectionModel = ui->tableView_case->selectionModel();

    // 检查是否有选中的项
    if (selectionModel->hasSelection())
    {
        // 获取选中的第一个项
        QModelIndex currentIndex  = selectionModel->selectedIndexes().first();
        if (currentIndex .isValid()) {
            // 假设我们关心第二列的数据（列索引为1）
            int columnToGet = 0;
            QModelIndex index = ui->tableView_case->model()->index(currentIndex .row(), columnToGet);
            QVariant data = ui->tableView_case->model()->data(index);

            // 根据需要转换数据类型
            QString stringData = data.toString();
            auto& sheetEkeCases= _ekeDataCache._sheetEkeCases;
            // 使用stringData
            for (auto sheetCase = sheetEkeCases.begin(); sheetCase !=sheetEkeCases.end(); ++sheetCase)
            {
                auto& ekeCaseTemp =sheetCase.value();
                if(ekeCaseTemp._mapEKEcase.keys().contains(stringData))
                {
                    QTcpSocket *_clientSocket = new QTcpSocket();
                    _clientSocket->connectToHost(ConfigData::strIP_EKE,ConfigData::strPort_EKE.toInt());
                    _clientSocket->waitForConnected(2000);     //网络连接时长建议大一点，否则可能出现连接失败
                    emit SendLogMsg(QString("EKE IP:%1,PORT：%2").arg(ConfigData::strIP_EKE).arg(ConfigData::strPort_EKE.toInt()));
                    if(_clientSocket->state()!=QAbstractSocket::ConnectedState)
                    {
                        emit SendLogMsg("连接codesys失败，线程退出");
                        _clientSocket->disconnectFromHost();
                        _clientSocket->waitForDisconnected();
                        return;
                    }
                    QString strError;
                    bool bresult= ChildCaseTestUnit(_clientSocket,ekeCaseTemp._mapEKEcase[stringData],strError);
                    //显示测试结果
                    showSingleCheckResult(stringData,bresult);
                    _clientSocket->disconnectFromHost();
                    _clientSocket->close();
                }
            }
        }
    }
}

void FormEKE::showSingleCheckResult(const QString& TCNumber,bool bPass)
{
    QAbstractItemModel *model = ui->tableView_case->model();

    // 遍历所有行和列
    for (int row = 0; row < model->rowCount(); ++row)
    {
        // 获取单元格数据，这里使用了Qt::DisplayRole来获取显示的文本
        //        QVariant data = model->data(model->index(row,EKETableFormat::casenumber), Qt::DisplayRole);
        QVariant data = model->data(model->index(row,0), Qt::DisplayRole);

        // 假设数据是字符串，将其转换为QString
        QString strData = data.toString();
        if(TCNumber==strData)
        {
            if(bPass)
            {
                model->setData(model->index(row, 6),"通过");
            }
            else
            {
                model->setData(model->index(row, 6),"未通过");
            }
        }
    }
}

void FormEKE::slotShowStatus()
{
    ui->le_endTime->setText(m_statusModel.m_strEndTime);
    ui->le_startTime->setText(m_statusModel.m_strStartTime);
}

void FormEKE::updateStatusInfo_Process(int rcentID)
{
    auto& result = _ekeDataCache._TestResult;
    int processCount=0;
    for (auto iter=_ekeDataCache._sheetEkeCases.begin();iter!=_ekeDataCache._sheetEkeCases.end();iter++)
    {
        processCount+=iter->_mapEKEcase.count();
    }

    int nPass=0;
    int unPass=0;
   for(auto iter=result.begin();iter!=result.end();iter++)
   {
        if(iter.value()._bPass)
        {
            nPass++;
        }
        else
        {
            unPass++;
        }
   }
   //id 0-25 实际项1-26
   QString textIndex = QString::number(rcentID+1)+"/"+QString::number(processCount);
   ui->label_index->setText(textIndex);

   ui->progressBar->setMaximum(processCount);
   ui->progressBar->setValue(rcentID+1);

   ui->le_pass->setText(QString::number(nPass));
   ui->le_unPass->setText(QString::number(unPass));

}

void FormEKE::slotBtnTestClicked()
{
    m_statusModel.start(500);
}

void FormEKE::slotBtnImportProtocalClicked()
{
    QString fileName = QFileHelper::FileSelect();
    if(fileName.isEmpty())
    {
        return;
    }
    LoadMVBPortCache loadMvb;
    loadMvb.LoadMVBPort(fileName,m_mvbProtoclaCache);

    //初始化缓存区域变量值
    for (auto iter = m_mvbProtoclaCache.m_portCache.begin(); iter!=m_mvbProtoclaCache.m_portCache.end(); iter++)
    {
        iter.value().initdata();
    }
    m_mvbProtoclaCache.TransCacheToDataPars();
    emit SendLogMsg("加载数据数量："+QString::number(m_mvbProtoclaCache.m_portCache.count()));
    //显示加载协议的信息
    slotShowProtoalData(m_mvbProtoclaCache);

}

void FormEKE::slotShowProtoalData(const MVBProtocalCache& mvbProtocalCache)
{
    m_treeModel->clear();

    ui->treeView->setEditTriggers(QAbstractItemView::DoubleClicked);
    //添加数据到控件
    m_treeModel->setHorizontalHeaderLabels(QStringList()<<"端口/变量名"<<"类型"<<"字节偏移"<<"位偏移"<<"值");
    // 添加根节点
    QStandardItem *rootNode = m_treeModel->invisibleRootItem();
            QStandardItem *PortItemRead = new QStandardItem("读");

            rootNode->appendRow(PortItemRead);
            QStandardItem *PortItemWrite = new QStandardItem("写");
            rootNode->appendRow(PortItemWrite);

    qDebug()<<"加载端口数据总数:"<<mvbProtocalCache.m_portDataPars.count()<<endl;
    for (auto iter = mvbProtocalCache.m_portDataPars.constBegin(); iter!= mvbProtocalCache.m_portDataPars.constEnd(); ++iter)
    {
        QStandardItem *PortItem = new QStandardItem(iter.key());
        PortItem->setFlags(PortItem->flags() & ~Qt::ItemIsEditable);

        //添加端口子项
        const auto childSection=iter.value();
        if(childSection.m_portType==1)  //源端口（发送）
        {
            PortItemWrite->appendRow(PortItem);
        }
        else if(childSection.m_portType==0)
        {
            PortItemRead->appendRow(PortItem); //宿端口（接受）
        }

        for (int i = 0; i < childSection.m_portVars.count(); ++i)
        {
            QStandardItem *item11 = new QStandardItem(childSection.m_portVars[i].m_VarName);
            item11->setFlags(item11->flags()&~Qt::ItemIsEditable);
            QStandardItem *item12 = new QStandardItem(childSection.m_portVars[i].m_MVBtype);
            item12->setFlags(item12->flags()&~Qt::ItemIsEditable);

            QStandardItem *item13 = new QStandardItem(QString::number(childSection.m_portVars[i].m_byteIndex));
            item13->setFlags(item13->flags()&~Qt::ItemIsEditable);
            QStandardItem *item14 = new QStandardItem(QString::number(childSection.m_portVars[i].m_bitIndex));
            item14->setFlags(item13->flags()&~Qt::ItemIsEditable);
            QStandardItem *item15 = new QStandardItem(childSection.m_portVars[i].m_cellValue.toString());
            item15->setFlags(item13->flags()|=Qt::ItemIsEditable);
            QList<QStandardItem*> items;
            items <<item11 << item12<<item13<< item14<<item15;

             PortItem->appendRow(items);
        }

    }
    // 设置模型
    ui->treeView->setModel(m_treeModel);
    QHeaderView *header =  ui->treeView->header();
    // 遍历所有列，并设置每一列为根据内容自适应
    int columns =  ui->treeView->model()->columnCount();
    for (int i = 0; i < columns; ++i) {
        header->setSectionResizeMode(i, QHeaderView::ResizeToContents);
    }
    // 显示树形视图
    ui->treeView->show();
}

void FormEKE::slotOnModelDataChange(const QModelIndex &modelId, const QVariant &value, const QVector<int> &roles)
{

    int varRowID=modelId.row();
    qDebug()<<modelId.column();

    //获取地址
    QString portAddress= modelId.parent().data().toString();

    //获取同列变量名
    QString varName = modelId.sibling(modelId.row(),modelId.column()-4).data().toString();
    //更改缓存值
    auto &varList= m_mvbProtoclaCache.m_portDataPars[portAddress].m_portVars;
    varList[varRowID].m_cellValue = value;

    m_mvbProtoclaCache.WritePortData(portAddress,varName,value,varRowID);
    //发送数据到转发工具
    m_clientForMVB.sendWriteMVBDataCommand(m_mvbProtoclaCache.m_portCache[portAddress]);

}


bool FormEKE::ChildCaseTestUnit(QTcpSocket *client, const EKEChildCase &childCase,QString& resultInfo)
{
//     emit SendProcedureMsg("测试名称:"+childCase._childCaseNumber);

     QString delayFunction;
     int delaySecond=0;
     if(!childCase._delayDescribe.isEmpty())
     {
        auto list=childCase._delayDescribe[0].split("_");
        if(list.count()==2)
        {
            delayFunction=list[0];
            delaySecond=list[1].toUpper().replace("S","").toInt();
        }
     }

    //输入变量读写比对
    CodesysWriteMsg josnWriteMsg;
    josnWriteMsg.appendData(childCase._inputs);

    //参数数量大于5的时候需进行分段（例如13 =5，5,3分三段）
    //1.发送输入参数写入指令
    QStringList writeVarCommand =josnWriteMsg.generateAllWriteMsg();
    emit SendLogMsg(QString("seg count：%1").arg(writeVarCommand.count()));
    for (int i = 0; i < writeVarCommand.count(); ++i)
    {
      emit SendLogMsg(writeVarCommand[i]);
      client->write(writeVarCommand[i].toUtf8());
      client->flush();
      client->waitForReadyRead(); //EKE服务端会给客户端发消息

      //2.读取输入返回结果
      QString tcpReceiveData= client->readAll();
      josnWriteMsg.addReveiveMsg(tcpReceiveData);
      emit SendLogMsg("recv:"+tcpReceiveData);
    }

    bool bWriteVarResOK=josnWriteMsg.WriteOK(resultInfo);

    if(!bWriteVarResOK)
      return false;

    QThread::sleep(delaySecond);
    QThread::msleep(1000);
    //输出变量读写比对
    CodesysReadMsg jsonReadmsg;
    jsonReadmsg.appendData(childCase._output);
    QStringList readVarCommand =jsonReadmsg.generateAllReadMsg();
    emit SendLogMsg(QString("seg count：%1").arg(readVarCommand.count()));
    for (int i = 0; i < readVarCommand.count(); ++i)
    {
      emit SendLogMsg(readVarCommand[i]);
      client->write(readVarCommand[i].toUtf8());
      client->flush();
      client->waitForReadyRead(); //EKE服务端会给客户端发消息

      //2.读取输入返回结果
      QString tcpReceiveData= client->readAll();

      jsonReadmsg.addReveiveMsg(tcpReceiveData);
      emit SendLogMsg(tcpReceiveData);
    }

    bool bReadVarResOK=jsonReadmsg.ReadOK(resultInfo);
    if(!bReadVarResOK)
      return false;

    return true;
}

